package top.eggcode.base;

import org.hibernate.Session;
import org.springframework.stereotype.Component;
import top.eggcode.common.exception.ApplicationException;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
import java.util.Optional;

/**
 * 实体类持久化工具
 * Title: DML工具
 * Description: TODO
 * Date: 2021/3/30 9:45
 *
 * @author JiaQi Ding
 * @version 1.0
 */
@Component
public class EntityStore {

    @PersistenceContext
    protected EntityManager manager;

    protected Session getSession() {
        return manager.unwrap(Session.class);
    }

    public <T> Optional<T> get(Class<T> entityClass, String id) {
        if (id == null) {
            throw new ApplicationException("参数：id，不能为空！");
        }
        return Optional.ofNullable(manager.find(entityClass, id));
    }

    public <T> List<T> selectAll(Class<T> entity) {
        String text = "from " +
                entity.getName();
        return manager.createQuery(text, entity).getResultList();
    }

    public <T> void add(T entity) {
        manager.persist(entity);
    }

    public <T> void batchAdd(List<T> entityList) {
        entityList.forEach(entity -> manager.persist(entity));
    }

    /**
     * 更新数据
     * 只针对未被JPA容器管理的实体
     *
     * @param entity 实体
     * @param <T>    ClassType
     */
    public <T> void update(T entity) {
        manager.merge(entity);
        manager.flush();
    }

    public <T> void nativeUpdate(List<T> entityList) {
        entityList.forEach(entity -> manager.merge(entity));
        manager.flush();
    }

    public <T> void delete(T entity) {
        manager.remove(entity);
    }

    /**
     * 移除对象
     * 针对持久化对象
     *
     * @param entityList 实体集合
     * @param <T>        ClassType
     */
    public <T> void nativeDelete(List<T> entityList) {
        entityList.forEach(entity -> manager.remove(entity));
    }


    public <T> List<?> query(String ql, List<Object> parameterList) {
        Query query = manager.createQuery(ql);
        int i = 1;
        for (Object parameter : parameterList) {
            query.setParameter(i, parameter);
            ++i;
        }
        return query.getResultList();
    }

    public int nativeUpdate(String ql, List<Object> parameterList) {
        Query query = manager.createQuery(ql);
        int i = 1;
        for (Object parameter : parameterList) {
            query.setParameter(i, parameter);
            ++i;
        }
        return query.executeUpdate();
    }

    public int nativeDelete(String ql, List<Object> parameterList) {
        Query query = manager.createQuery(ql);
        int i = 1;
        for (Object parameter : parameterList) {
            query.setParameter(i, parameter);
            ++i;
        }
        return query.executeUpdate();
    }

    public <T> void refresh(T entity) {
        manager.refresh(entity);
    }

    public void flush() {
        manager.flush();
    }
}
